import tkinter
from tkinter import filedialog
from tkinter import messagebox
import tkinter.simpledialog
from PIL import Image, ImageTk
import paho.mqtt.client as mqtt
import json
import webbrowser


class MqttMonitoring(object):

    def __init__(self):
        self.client = mqtt.Client()
        # self.client.connect("192.168.0.121", 1883, 600)  # 默认内网测试，可设置的哦
        self.client.connect("test.ranye-iot.net", 1883, 600)  # 默认公网测试
        self.client.loop_start()


class windows(object):
    image = None
    im = None
    strv_soilrh = None
    strv_temp = None
    strv_rh = None
    lb_strv_temp = None
    lb_strv_rh = None
    TEMP_MIN = 13  # 默认温度最低警告值
    TEMP_MAX = 25  # 默认温度最高警告值
    RH_MIN = 60  # 默认湿度最低警告值
    RH_MAX = 65  # 默认湿度最高警告值

    def __init__(self):

        self.mqtt_monitor = MqttMonitoring()
        self.mqtt_monitor.client.subscribe("GreenHouse-Pub-Data", 1)
        self.mqtt_monitor.client.on_message = self.on_message_come

        self.win = tkinter.Tk()
        self.win.title("智能温室环境监测")
        try:
            self.win.iconbitmap('u.ico')  # 窗口图标设置
        except Exception as error:
            messagebox.showerror(title="Error", message=f"Fail to find the u.ico.\n{error}")

        self.win_lenth_hight(600, 400)
        self.entry_control()

        self.win.mainloop()

    def win_lenth_hight(self, w, h):
        """
        设置窗口大小，并将窗口居中
        :param w: 长
        :param h: 高
        :return: None
        """
        width = w  # 长
        height = h  # 高
        temp = "%sx%s" % (width, height)
        self.win.geometry(temp)  # 设置窗口大小
        # 设置窗口是否可变长、宽，True：可变，False：不可变
        self.win.resizable(width=False, height=False)

        # 获取屏幕尺寸以计算布局参数，使窗口居屏幕中央
        screenwidth = self.win.winfo_screenwidth()
        screenheight = self.win.winfo_screenheight()
        temp_01 = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
        self.win.geometry(temp_01)

    def entry_control(self):
        self.entry_backgroundImg("1.jpg")

        # 放置静态文本
        lb_temp = tkinter.Label(self.win, text="温室温度：", font=('方正等线', 18))
        lb_temp.place(x=125, y=20)

        lb_rh = tkinter.Label(self.win, text="温室湿度：", font=('方正等线', 18))
        lb_rh.place(x=125, y=70)

        lb_soil_rh = tkinter.Label(self.win, text="温室土壤湿度：", font=('方正等线', 18))
        lb_soil_rh.place(x=110, y=120)

        lb_about = tkinter.Label(self.win, text="by TimeChicken\n更多请点这里.", font=('方正等线', 14))
        lb_about.bind("<Button-1>", self.open_url)
        lb_about.place(x=370, y=340)

        # 放置动态文本
        self.strv_temp = tkinter.StringVar()
        self.strv_temp.set("None")
        self.lb_strv_temp = tkinter.Label(self.win, textvariable=self.strv_temp, font=('方正等线', 18))
        self.lb_strv_temp.place(x=300, y=20)

        self.strv_rh = tkinter.StringVar()
        self.strv_rh.set("None")
        self.lb_strv_rh = tkinter.Label(self.win, textvariable=self.strv_rh, font=('方正等线', 18))
        self.lb_strv_rh.place(x=300, y=70)

        self.strv_soilrh = tkinter.StringVar()
        self.strv_soilrh.set("None")
        lb_strv_soilrh = tkinter.Label(self.win, textvariable=self.strv_soilrh, font=('方正等线', 18))
        lb_strv_soilrh.place(x=300, y=120)

        # 放置设置温度阈值按钮
        bt_threshold_temp = tkinter.Button(self.win, text='设置', relief='flat', command=self.set_temp_threshold,
                                           font=('方正等线', 12))
        bt_threshold_temp.place(x=400, y=20)

        bt_threshold_rh = tkinter.Button(self.win, text='设置', relief='flat', command=self.set_rh_threshold,
                                         font=('方正等线', 12))
        bt_threshold_rh.place(x=400, y=70)

        bt_threshold_soilrh = tkinter.Button(self.win, text='设置', relief='flat', command=self.set_soilrh_threshold,
                                             font=('方正等线', 12))
        bt_threshold_soilrh.place(x=400, y=120)

        bt_showabout = tkinter.Button(self.win, text="关于", font=('方正等线', 18), width=10, command=self.showabout)
        bt_showabout.place(x=150, y=200)

        bt_showabout = tkinter.Button(self.win, text="网络设置", font=('方正等线', 18), width=10, command=self.mqtt_reconnect)
        bt_showabout.place(x=330, y=200)

    def entry_backgroundImg(self, img_path):
        try:
            self.image = Image.open(img_path).resize((1200, 800))
        except Exception as error:
            messagebox.showerror(title="Error", message="Fail to find the " + img_path + f".\n{error}")
        canvas = tkinter.Canvas(self.win, width=self.image.width, height=self.image.height)
        self.im = ImageTk.PhotoImage(self.image)
        canvas.create_image(0, 0, image=self.im)
        canvas.place(x=0, y=0)

    def set_temp_threshold(self):
        result = tkinter.simpledialog.askstring(title='修改温度阈值',
                                                prompt='请按格式输入阈值范围：',
                                                initialvalue="最低温度-最高温度")

        if result is None or result == "":
            return
        result = '$' + result  # 添加温度命令控制字符
        self.mqtt_monitor.client.publish('GreenHouse-Pub-SetThreshold', payload=result, qos=1)
        messagebox.showinfo(title="提示", message="设置温度阈值成功！！！")

        self.TEMP_MAX = int(result[result.find("-") + 1:])
        self.TEMP_MIN = int(result[result.find('$') + 1:result.find('-')])

    def set_rh_threshold(self):
        result = tkinter.simpledialog.askstring(title='修改湿度阈值',
                                                prompt='请按格式输入阈值范围(%)：',
                                                initialvalue="最低湿度-最高湿度")
        if result is None or result == "":
            return
        result = '#' + result  # 添加湿度命令控制字符
        self.mqtt_monitor.client.publish('GreenHouse-Pub-SetThreshold', payload=result, qos=1)
        messagebox.showinfo(title='提示', message="设置湿度阈值成功！！！")
        self.RH_MAX = int(result[result.find('-') + 1:])
        self.RH_MIN = int(result[result.find('#') + 1:result.find('-')])

    def set_soilrh_threshold(self):
        messagebox.showinfo(title="提示", message="该功能尚未开发，敬请期待！")

    def on_message_come(self, lient, userdata, msg):
        recv_data = json.loads(str(msg.payload.decode()))

        # 更新数据
        if recv_data.__contains__('temp'):

            if recv_data['temp'] > self.TEMP_MAX:
                self.lb_strv_temp.config(fg="red")
            elif self.TEMP_MIN <= recv_data['temp'] <= self.TEMP_MAX:
                self.lb_strv_temp.config(fg="black")
            else:
                self.lb_strv_temp.config(fg="blue")

            if recv_data['rh'] > self.RH_MAX:
                self.lb_strv_rh.config(fg="red")
            elif self.RH_MIN <= recv_data['rh'] <= self.RH_MAX:
                self.lb_strv_rh.config(fg="black")
            else:
                self.lb_strv_rh.config(fg="blue")

            self.win.update_idletasks()  # 更新窗口驱动

            self.strv_temp.set(str(recv_data['temp']) + " ℃")
            self.strv_rh.set(str(recv_data['rh']) + " %")
        elif recv_data.__contains__('soil_rh'):
            # 因为收到的是电压单位，故需要转换（3300代表3.3V）
            self.strv_soilrh.set(str(int(float("%.2f" % (recv_data['soil_rh']/3300)) * 100)) + " %")

    def mqtt_reconnect(self):

        result = tkinter.simpledialog.askstring(title='MQTT网络设置',
                                                prompt='请按格式输入网址及端口：',
                                                initialvalue="网址:端口号")
        if result is None or result == "":
            return

        self.mqtt_monitor.client.loop_stop()
        try:
            self.mqtt_monitor.client.connect(host=result[:result.find(':')], port=int(result[result.find(':') + 1:]))

            self.mqtt_monitor.client.subscribe("GreenHouse-Pub-Data", 1)
            messagebox.showinfo(title='提示', message="已成功连接至 " + result + ".")
        except Exception as error:
            messagebox.showerror(title='错误', message=f"网络连接错误，请重新检查并连接网络！！！\n{error}")
        finally:
            self.mqtt_monitor.client.loop_start()

    @staticmethod
    def showabout():
        messagebox.showinfo(title="关于软件", message="作者：时光鸡\n"
                                                  "开发时间：2021-1-10\n"
                                                  "软件名：智能温室环境监测\n"
                                                  "简介：自豪的使用python.tkinter及paho.mqtt")

    @staticmethod
    def open_url(event):
        webbrowser.open("http://219.222.251.56:12100/cgi-bin/browse_file.py", new=0)


try:
    dapengjiance = windows()
except Exception as err:
    messagebox.showerror(title="未知错误", message="出现未知错误，请联系软件作者!!!\n"
                                               "错误信息：" + str(err))
